﻿using Microsoft.Extensions.DependencyInjection;
using QModels;
using QServices.Services;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QServices
{
	public class QPlcManager
	{

		Plc m_plc;

		public QPlcManager()
		{
			var info = AppRuntime.GetService().GetRequiredService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
			m_plc = new Plc((CpuType)info.PlcType, info.IP, 0, 1);
		}
		public QPlcManager(AgvCar info)
		{
			m_plc = new Plc((CpuType)info.PlcType, info.IP, 0, 1);
		}
		public Plc GetPlc()
		{
			if (m_plc == null)
			{
				var info = AppRuntime.GetService().GetRequiredService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
				m_plc = new Plc((CpuType)info.PlcType, info.IP, 0, 1);
			}
			if (!m_plc.IsConnected) m_plc.Open();
			return m_plc;
		}


		public bool 开机()
		{
			var res = (bool)GetPlc().Read(QplcAddress.开机);

			return res;
		}


		public bool 充电()
		{
			var res = (bool)GetPlc().Read(QplcAddress.充电);
			return res;
		}
		public bool 通讯正常()
		{
			var res = (bool)GetPlc().Read(QplcAddress.通讯正常);
			return res;
		}
		public bool 故障全部()
		{
			var res = (bool)GetPlc().Read(QplcAddress.故障全部);
			return res;
		}
		public bool 喂料中()
		{
			var res = (bool)GetPlc().Read(QplcAddress.喂料中);
			return res;
		}
		public bool 本次喂料完成()
		{
			var res = (bool)GetPlc().Read(QplcAddress.本次喂料完成);
			return res;
		}
		public bool 故障左行走()
		{
			var res = (bool)GetPlc().Read(QplcAddress.故障左行走);
			return res;
		}
		public bool 故障右行走()
		{
			var res = (bool)GetPlc().Read(QplcAddress.故障右行走);
			return res;
		}
		public bool 故障左喂料()
		{
			var res = (bool)GetPlc().Read(QplcAddress.故障左喂料);
			return res;
		}
		public bool 故障右喂料()
		{
			var res = (bool)GetPlc().Read(QplcAddress.故障右喂料);
			return res;
		}
		public bool 小车急停()
		{
			var res = (bool)GetPlc().Read(QplcAddress.小车急停);
			return res;
		}
		public bool 电池报警()
		{
			var res = (bool)GetPlc().Read(QplcAddress.电池报警);
			return res;
		}
		public bool 左出轨()
		{
			var res = (bool)GetPlc().Read(QplcAddress.左出轨);
			return res;
		}
		public bool 右出轨()
		{
			var res = (bool)GetPlc().Read(QplcAddress.右出轨);
			return res;
		}
		public bool 弯道超时()
		{
			var res = (bool)GetPlc().Read(QplcAddress.弯道超时);
			return res;
		}
		public bool 前有障碍物()
		{
			var res = (bool)GetPlc().Read(QplcAddress.前有障碍物);
			return res;
		}


		public (int YEAR, int MONTH, int DAY, int WEEKDAY, int HOUR, int MINUTE, int SECOND, int NANOSECOND) GetDateTime()
		{
			var plc = GetPlc();
			var year = (short)plc.Read(DataType.DataBlock, 1000, 2, VarType.Int, 1);
			var month = (byte)plc.Read(DataType.DataBlock, 1000, 4, VarType.Byte, 1);
			var day = (byte)plc.Read(DataType.DataBlock, 1000, 5, VarType.Byte, 1);
			var weekday = (byte)plc.Read(DataType.DataBlock, 1000, 6, VarType.Byte, 1);
			var hour = (byte)plc.Read(DataType.DataBlock, 1000, 7, VarType.Byte, 1);
			var minute = (byte)plc.Read(DataType.DataBlock, 1000, 8, VarType.Byte, 1);
			var second = (byte)plc.Read(DataType.DataBlock, 1000, 9, VarType.Byte, 1);
			var nanosecond = (int)plc.Read(DataType.DataBlock, 1000, 9, VarType.DInt, 1);


			return (year, month, day, weekday, hour, minute, second, nanosecond);
		}


		public string GetBarCode()
		{
			if (AppRuntime.IsDebug) return "A0100904-0000-0000-0000-000000000000";

			var plc = GetPlc();
			var xx = plc.Read(DataType.DataBlock, 1000, 14, VarType.String, 36);
			var res = xx.ToString();
			return res;

		}
		public bool[] GetBasePointLR()
		{
			var plc = GetPlc();
			var res = new bool[8];
			var bytes_119 = plc.ReadBytes(DataType.DataBlock, 1000, 0, 1);
			if (bytes_119 != null && bytes_119.Length == 1)
			{

				for (int i = 0; i < 8; i++)
				{
					res[i] = bytes_119[0].SelectBit(i);
				}

			}
			return res;
		}

		public string 当前喂料笼数()
		{
			var plc = GetPlc();
			var res = plc.Read(DataType.DataBlock, 1000, 50, VarType.DWord, 1).ToString();

			return res;
		}

		public decimal 当前电量()
		{
			if (AppRuntime.IsDebug) return 180;

			var plc = GetPlc();
			var res = plc.Read(DataType.DataBlock, 1000, 54, VarType.DWord, 1).ToString();
			int.TryParse(res, out var eleqty);
			if (eleqty > 0)
			{
				return (eleqty / 10.0m);
			}
			return eleqty;
		}

		public AGVCarStatusModel GetGVCarStatusModel()
		{
			var res = new AGVCarStatusModel();
			res.CarNumber = AppRuntime.CarNumber;
			try
			{

				var plc = GetPlc();
				//var xx = (int)(byte)plc.Read(DataType.DataBlock, 1000, 0, VarType.Byte, 1);
				var bytes_0 = plc.ReadBytes(DataType.DataBlock, 1000, 0, 2); 

				//var status_0 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 0, VarType.Byte, 1);
				//var status_1 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 1, VarType.Byte, 1);

				var FeedCups = (int)(uint)plc.Read(DataType.DataBlock, 1000, 50, VarType.DWord, 1);
				var CurrentBattery = (int)(uint)plc.Read(DataType.DataBlock, 1000, 54, VarType.DWord, 1);
				var ServoStatus_L1 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 110, VarType.Byte, 1);
				var ServoStatus_L2 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 111, VarType.Byte, 1);
				var ServoStatus_L3 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 112, VarType.Byte, 1);
				var ServoStatus_L4 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 113, VarType.Byte, 1);
				var ServoStatus_R1 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 114, VarType.Byte, 1);
				var ServoStatus_R2 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 115, VarType.Byte, 1);
				var ServoStatus_R3 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 116, VarType.Byte, 1);
				var ServoStatus_R4 = (int)(byte)plc.Read(DataType.DataBlock, 1000, 117, VarType.Byte, 1);
				var ServoUseStatus = (int)(byte)plc.Read(DataType.DataBlock, 1000, 118, VarType.Byte, 1);
				var BarCode = plc.Read(DataType.DataBlock, 1000, 14, VarType.String, 36).ToString();


				
				if (bytes_0.Length == 2)
				{
					res.IsOpen = bytes_0[0].SelectBit(0);
					res.ChongDian = bytes_0[0].SelectBit(1);
					res.TongXinOK= bytes_0[0].SelectBit(2);
					res.GuZhangQuanBu= bytes_0[0].SelectBit(3);
					res.WeiLiaoZhong= bytes_0[0].SelectBit(4);
					res.WeiLiaoWanCheng= bytes_0[0].SelectBit(5);
					res.GuZhangLeft= bytes_0[0].SelectBit(6);
					res.GuZhangRight= bytes_0[0].SelectBit(7);


					res.GuZhangFeedLeft= bytes_0[1].SelectBit(0);
					res.GuZhangFeedRight= bytes_0[1].SelectBit(1);
					res.EmergencyStop= bytes_0[1].SelectBit(2);
					res.BatteryAlarm= bytes_0[1].SelectBit(3);
					res.ChuGuiLeft= bytes_0[1].SelectBit(4);
					res.ChuGuiRight= bytes_0[1].SelectBit(5);
					res.CornersTimedOut= bytes_0[1].SelectBit(6);


				}

				
				res.FeedCups = FeedCups;
				res.CurrentBattery = CurrentBattery;
				res.ServoStatus_L1 = ServoStatus_L1;
				res.ServoStatus_L2 = ServoStatus_L2;
				res.ServoStatus_L3 = ServoStatus_L3;
				res.ServoStatus_L4 = ServoStatus_L4;
				res.ServoStatus_R1 = ServoStatus_R1;
				res.ServoStatus_R2 = ServoStatus_R2;
				res.ServoStatus_R3 = ServoStatus_R3;
				res.ServoStatus_R4 = ServoStatus_R4;
				res.ServoUseStatus = ServoUseStatus;

				var FeedArrays = new List<int>();
				var index = 0;
				for (int i = 78; i <= 106; i += 4)
				{
					var tt = (int)(uint)plc.Read(DataType.DataBlock, 1000, i, VarType.DWord, 1);
					FeedArrays.Add(tt);
				}
				res.BarCode = BarCode;
				res.FeedTotal = string.Join(",", FeedArrays);
				var bytes_119 = plc.ReadBytes(DataType.DataBlock, 1000, 0, 1);
				if(bytes_119 != null && bytes_119.Length==1)
				{
					var sb =new List<string>();
					if (!bytes_119[0].SelectBit(0)) sb.Add("L1");
					if (!bytes_119[0].SelectBit(1)) sb.Add("L2");
					if (!bytes_119[0].SelectBit(2)) sb.Add("L3");
					if (!bytes_119[0].SelectBit(3)) sb.Add("L4");
					if (!bytes_119[0].SelectBit(4)) sb.Add("R1");
					if (!bytes_119[0].SelectBit(5)) sb.Add("R2");
					if (!bytes_119[0].SelectBit(6)) sb.Add("R3");
					if (!bytes_119[0].SelectBit(7)) sb.Add("R4");
					res.BasePointLR = string.Join(",", sb);
				}

			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}



			return res;
		}

		/// <summary>
		/// 获取当前杯数
		/// </summary>
		/// <returns></returns>
		public AgvFeedCupModel GetAgvFeedCupModel()
		{
			var res=new AgvFeedCupModel();
			try
			{
				var plc = GetPlc();
				var L1 = (int)plc.Read(DataType.DataBlock, 1000, 126, VarType.DInt, 1);
				var L2 = (int)plc.Read(DataType.DataBlock, 1000, 130, VarType.DInt, 1);
				var L3 = (int)plc.Read(DataType.DataBlock, 1000, 134, VarType.DInt, 1);
				var L4 = (int)plc.Read(DataType.DataBlock, 1000, 138, VarType.DInt, 1);
				var R1 = (int)plc.Read(DataType.DataBlock, 1000, 142, VarType.DInt, 1);
				var R2 = (int)plc.Read(DataType.DataBlock, 1000, 146, VarType.DInt, 1);
				var R3 = (int)plc.Read(DataType.DataBlock, 1000, 150, VarType.DInt, 1);
				var R4 = (int)plc.Read(DataType.DataBlock, 1000, 154, VarType.DInt, 1);
				res.L1 = L1;
				res.L2 = L2;
				res.L3 = L3;
				res.L4 = L4;
				res.R1 = R1;
				res.R2 = R2;
				res.R3 = R3;
				res.R4 = R4;
			}
			catch(Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}


			return res;
		}

		/// <summary>
		/// 上位机 下达清零喂料杯数
		/// </summary>
		public void ClearAgvFeedCupModel()
		{
			try
			{
				var plc = GetPlc();
				plc.Write("DB1000.DBX76.2", true);

			}
			catch(Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}
		}

		public void CheckCarElectricQty()
		{

		}

		#region  写入数据

		public void 启动小车()
		{
			var plc = GetPlc();
			plc.Write(DataType.DataBlock, 1000, 0, 1, 0);
		}

		public void 上位机下达允许喂料(bool IsOK)
		{
			if (AppRuntime.IsDebug) return;
			var plc = GetPlc();
			var value = IsOK ? 1 : 0;
			plc.Write(DataType.DataBlock, 1000, 76, value, 0);
		}
		public void 上位机下达急停(bool IsOk)
		{
			var plc = GetPlc();
			var value = IsOk ? 1 : 0;
			plc.Write(DataType.DataBlock, 1000, 76, value, 1);
		}
		public void 上位机下达早喂料开始时间(DosingSchedule info)
		{
			var plc = GetPlc();
			var seonds = info.HourFirst * 60 * 60 + info.MinuteFirst * 60;
			plc.Write(DataType.DataBlock, 1000, 64, seonds);
		}
		public void 上位机下达中喂料开始时间(DosingSchedule info)
		{
			var plc = GetPlc();
			var seonds = info.HourSecond * 60 * 60 + info.MinuteSecond * 60;
			plc.Write(DataType.DataBlock, 1000, 68, seonds);
		}
		public void 上位机下达晚喂料开始时间(DosingSchedule info)
		{
			var plc = GetPlc();
			var seonds = info.HourThird * 60 * 60 + info.MinuteThird * 60;
			plc.Write(DataType.DataBlock, 1000, 72, seonds);
		}

		public void 上位机下达喂料开始时间(DosingSchedule info)
		{
			var plc = GetPlc();
			var seonds_0 = info.HourFirst * 60 * 60 + info.MinuteFirst * 60;
			var seonds_1 = info.HourSecond * 60 * 60 + info.MinuteSecond * 60;
			var seonds_2 = info.HourThird * 60 * 60 + info.MinuteThird * 60;
			plc.Write(DataType.DataBlock, 1000, 64, seonds_0);
			plc.Write(DataType.DataBlock, 1000, 68, seonds_0);
			plc.Write(DataType.DataBlock, 1000, 72, seonds_0);
		}
		public void 上位机喂料量下达(int[] values)
		{
			if (AppRuntime.IsDebug) return;
			var plc = GetPlc();
			plc.Write(DataType.DataBlock, 1000, 78, values);

		}

		/// <summary>
		/// 开启小车充电
		/// </summary>

		public void StartCarElectric()
		{
			try
			{
				var plc = GetPlc();
				plc.Write("DB1000.DBX76.5", 0);
				Thread.Sleep(1000 * 5);
				plc.Write("DB1000.DBX76.5", 1);

			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}
		}

		/// <summary>
		/// 停止小车充电
		/// </summary>
		public void EndCarElectric()
		{
			try
			{
				var plc = GetPlc();
				plc.Write("DB1000.DBX76.5", 0);

			}
			catch (Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}
		}

		public void UpdateCarMaxMinElectricQty(int minQty,int maxQty)
		{
			if (AppRuntime.IsDebug) return;

			try
			{
				var plc = GetPlc();

				plc.Write(DataType.DataBlock, 1000, 134, minQty);
				plc.Write(DataType.DataBlock, 1000, 136, maxQty);
			}
			catch(Exception ex)
			{
				AppRuntime.Logger_Error(ex);
			}
			

		}


		#endregion

	}
}
